import type {
  DatePickerClearSlotProps,
  DatePickerNowSlotProps
} from '../public-types'
import { defineComponent, h, type PropType, watchEffect } from 'vue'
import { NBaseFocusDetector } from '../../../_internal'
import {
  BackwardIcon,
  FastBackwardIcon,
  FastForwardIcon,
  ForwardIcon
} from '../../../_internal/icons'
import { resolveSlot, resolveSlotWithProps, warnOnce } from '../../../_utils'
import { NButton, NxButton } from '../../../button'
import PanelHeader from './panelHeader'
import { useCalendar, useCalendarProps } from './use-calendar'

/**
 * Date Panel
 * Update picker value on:
 * 1. item click
 * 2. clear click
 */
export default defineComponent({
  name: 'DatePanel',
  props: {
    ...useCalendarProps,
    type: {
      type: String as PropType<'date' | 'week'>,
      required: true
    }
  },
  setup(props) {
    if (__DEV__) {
      watchEffect(() => {
        if (props.actions?.includes('confirm')) {
          warnOnce(
            'date-picker',
            'The `confirm` action is not supported for n-date-picker of `date` type'
          )
        }
      })
    }
    return useCalendar(props, props.type)
  },
  render() {
    const { mergedClsPrefix, mergedTheme, shortcuts, onRender, $slots, type }
      = this
    onRender?.()
    return (
      <div
        ref="selfRef"
        tabindex={0}
        class={[
          `${mergedClsPrefix}-date-panel`,
          `${mergedClsPrefix}-date-panel--${type}`,
          !this.panel && `${mergedClsPrefix}-date-panel--shadow`,
          this.themeClass
        ]}
        onFocus={this.handlePanelFocus}
        onKeydown={this.handlePanelKeyDown}
      >
        <div class={`${mergedClsPrefix}-date-panel-calendar`}>
          <div class={`${mergedClsPrefix}-date-panel-month`}>
            <div
              class={`${mergedClsPrefix}-date-panel-month__fast-prev`}
              onClick={this.prevYear}
            >
              {resolveSlot($slots['prev-year'], () => [<FastBackwardIcon />])}
            </div>
            <div
              class={`${mergedClsPrefix}-date-panel-month__prev`}
              onClick={this.prevMonth}
            >
              {resolveSlot($slots['prev-month'], () => [<BackwardIcon />])}
            </div>
            <PanelHeader
              monthYearSeparator={this.calendarHeaderMonthYearSeparator}
              monthBeforeYear={this.calendarMonthBeforeYear}
              value={this.calendarValue}
              onUpdateValue={this.onUpdateCalendarValue}
              mergedClsPrefix={mergedClsPrefix}
              calendarMonth={this.calendarMonth}
              calendarYear={this.calendarYear}
            />
            <div
              class={`${mergedClsPrefix}-date-panel-month__next`}
              onClick={this.nextMonth}
            >
              {resolveSlot($slots['next-month'], () => [<ForwardIcon />])}
            </div>
            <div
              class={`${mergedClsPrefix}-date-panel-month__fast-next`}
              onClick={this.nextYear}
            >
              {resolveSlot($slots['next-year'], () => [<FastForwardIcon />])}
            </div>
          </div>
          <div class={`${mergedClsPrefix}-date-panel-weekdays`}>
            {this.weekdays.map(weekday => (
              <div
                key={weekday}
                class={`${mergedClsPrefix}-date-panel-weekdays__day`}
              >
                {weekday}
              </div>
            ))}
          </div>
          <div class={`${mergedClsPrefix}-date-panel-dates`}>
            {this.dateArray.map((dateItem, i) => (
              <div
                data-n-date
                key={i}
                class={[
                  `${mergedClsPrefix}-date-panel-date`,
                  {
                    [`${mergedClsPrefix}-date-panel-date--current`]:
                      dateItem.isCurrentDate,
                    [`${mergedClsPrefix}-date-panel-date--selected`]:
                      dateItem.selected,
                    [`${mergedClsPrefix}-date-panel-date--excluded`]:
                      !dateItem.inCurrentMonth,
                    [`${mergedClsPrefix}-date-panel-date--disabled`]:
                      this.mergedIsDateDisabled(dateItem.ts, {
                        type: 'date',
                        year: dateItem.dateObject.year,
                        month: dateItem.dateObject.month,
                        date: dateItem.dateObject.date
                      }),
                    [`${mergedClsPrefix}-date-panel-date--week-hovered`]:
                      this.isWeekHovered(dateItem),
                    [`${mergedClsPrefix}-date-panel-date--week-selected`]:
                      dateItem.inSelectedWeek
                  }
                ]}
                onClick={() => {
                  this.handleDateClick(dateItem)
                }}
                onMouseenter={() => {
                  this.handleDateMouseEnter(dateItem)
                }}
              >
                <div class={`${mergedClsPrefix}-date-panel-date__trigger`} />
                {dateItem.dateObject.date}
                {dateItem.isCurrentDate ? (
                  <div class={`${mergedClsPrefix}-date-panel-date__sup`} />
                ) : null}
              </div>
            ))}
          </div>
        </div>
        {this.datePickerSlots.footer ? (
          <div class={`${mergedClsPrefix}-date-panel-footer`}>
            {this.datePickerSlots.footer()}
          </div>
        ) : null}
        {this.actions?.length || shortcuts ? (
          <div class={`${mergedClsPrefix}-date-panel-actions`}>
            <div class={`${mergedClsPrefix}-date-panel-actions__prefix`}>
              {shortcuts
              && Object.keys(shortcuts).map((key) => {
                const shortcut = shortcuts[key]
                return Array.isArray(shortcut) ? null : (
                  <NxButton
                    size="tiny"
                    onMouseenter={() => {
                      this.handleSingleShortcutMouseenter(shortcut)
                    }}
                    onClick={() => {
                      this.handleSingleShortcutClick(shortcut)
                    }}
                    onMouseleave={() => {
                      this.handleShortcutMouseleave()
                    }}
                  >
                    {{ default: () => key }}
                  </NxButton>
                )
              })}
            </div>
            <div class={`${mergedClsPrefix}-date-panel-actions__suffix`}>
              {this.actions?.includes('clear')
                ? resolveSlotWithProps(
                    this.$slots.clear,
                    {
                      onClear: this.handleClearClick,
                      text: this.locale.clear
                    } satisfies DatePickerClearSlotProps,
                    () => [
                      <NButton
                        theme={mergedTheme.peers.Button}
                        themeOverrides={mergedTheme.peerOverrides.Button}
                        size="tiny"
                        onClick={this.handleClearClick}
                      >
                        {{ default: () => this.locale.clear }}
                      </NButton>
                    ]
                  )
                : null}
              {this.actions?.includes('now')
                ? resolveSlotWithProps(
                    this.$slots.now,
                    {
                      onNow: this.handleNowClick,
                      text: this.locale.now
                    } satisfies DatePickerNowSlotProps,
                    () => [
                      <NButton
                        theme={mergedTheme.peers.Button}
                        themeOverrides={mergedTheme.peerOverrides.Button}
                        size="tiny"
                        onClick={this.handleNowClick}
                      >
                        {{ default: () => this.locale.now }}
                      </NButton>
                    ]
                  )
                : null}
              {/** we don't need a confirm button for date picking */}
            </div>
          </div>
        ) : null}
        <NBaseFocusDetector onFocus={this.handleFocusDetectorFocus} />
      </div>
    )
  }
})
